/* 
 *	Copyright (C) 2009-2010 miaohua
 *	http://code.google.com/p/lrcshower/
 *
 *  This Program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *   
 *  This Program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *   
 *  You should have received a copy of the GNU General Public License
 *  along with GNU Make; see the file COPYING.  If not, write to
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
 *  http://www.gnu.org/copyleft/gpl.html
 *
 */

#pragma once
#include <vector>
#include <string>
#include "TypeDef.h"
#include "OleDropTargetEx.h"

enum EScrollDirection
{
	ScrollNull,
	ScrollUp,
	ScrollDown
};

enum DLDropFlags
{
	DL_ACCEPT_FILES =       0x01,	// Allow files to be dropped
	DL_ACCEPT_FOLDERS =		0x02,	// Allow folders to be droppped
	DL_ALLOW_DUPLICATES =	0x04,	// Allow a pathname to be dropped even if its already in the list (ignored if you specify a callback function)
	DL_FILTER_EXTENSION =	0x08,	// Only accept files with the specified extension. Specify in csFileExt
	DL_ADD_CALLBACK =		0x10,	// Receive a callback for each item dropped, specified in pfnCallback (you have responsibility for inserting items into the list)
    DL_ADDFINISH_CALLBACK = 0x20,
    DL_TIP_CALLBACK =       0x40,   // Receive a callback for each item show tips

	DL_FOLDER_TYPE =		0x80,	// Returned to the callback function - indicating the type of path dropped
	DL_FILE_TYPE =			0x100
};

typedef void (* DROP_FILES_CALLBACK)(CListCtrl*, const CString&, void*);
typedef void (* DROP_ITEMS_CALLBACK)(CListCtrl*, int SrcIdx, int DestIdx, void *);
typedef void (* GET_SONGTIP_CALLBACK)(CListCtrl*, unsigned int, tstring &);
typedef void (* DROPITEM_FINISH_CALLBACK)(CListCtrl* List, int StartRowIdx, int EndRowIdx);
typedef void (* DROPFILE_START_CALLBACK)(CListCtrl* List, int FileNum);
typedef void (* DROPFILE_FINISH_CALLBACK)(CListCtrl* List, int StartRowIdx, int EndRowIdx, int FilesNum);


// Drop parameters
// If there are more than one ext want to be checked, just use semicolon to 
// separate them, just like "mp3;wma"(Note: the last one is no semicolon
// If there is only one ext need to be checked, just put it be like "mp3" with no semicolon
struct LISTMODE
{ 
	unsigned int m_DropMask;		        // Specifies what type of items to accept - a combination of the above flags
	tstring m_FileExt;			            // The file extension on which to filter. Use the format ".extension". Ignored unless DL_FILTER_EXTENSION is specified
	DROP_FILES_CALLBACK m_DropFileCallback;	    // Address of your callback function. Ignored unless DL_USE_CALLBACK is specified
    DROP_ITEMS_CALLBACK m_DropItemCallback;
    GET_SONGTIP_CALLBACK m_GetTipCallback;
    DROPITEM_FINISH_CALLBACK m_DropItemFinishCallback;
    DROPFILE_START_CALLBACK m_DropFileStartCallback;
    DROPFILE_FINISH_CALLBACK m_DropFileFinishCallback;
    
}; 

struct DropItemsParam
{
   std::vector<tstring> m_ColumVals;
   DWORD_PTR m_UserData;
};

struct DropFilesParam
{
   std::vector<tstring> m_ColumVals;
   tstring m_FullPath;
   DWORD_PTR m_UserData;
   int m_RowIdx;
};

class CListCtrlEx : public CListCtrl
{
	DECLARE_DYNAMIC(CListCtrlEx)

// Construction
public:
	CListCtrlEx();
	virtual ~CListCtrlEx();

    BOOL EnableTips();
 	bool SetCtrlMode(const LISTMODE & CtrlMode);
    void SetPlayTextClr(COLORREF  Color);
    void SetPlayTextBgClr(COLORREF Color);
    void SetCurSongIdx(int Idx);
    void ClearAllSel();
	LISTMODE GetCtrlMode() const { return m_CtrlMode; };

    void OleInitialize();
    virtual DROPEFFECT OnDragEnter(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point);
    virtual DROPEFFECT OnDragOver(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point);
    virtual DROPEFFECT OnDropEx(CWnd* pWnd, COleDataObject* pDataObject, DROPEFFECT dropEffect, DROPEFFECT dropList, CPoint point);
    virtual BOOL OnDrop(CWnd* pWnd, COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point);
    virtual void OnDragLeave(CWnd* pWnd);

protected:
	void DropItem();
	void RestorePrevDropItemState();
	void UpdateSelection(int DropIndex);
	void SetScrollTimer(EScrollDirection ScrollDirection, int TimerId);
	void KillScrollTimer(int TimerId);
	CImageList* CreateDragImageEx(LPPOINT Pt);
    int InsertPathName(const DropFilesParam * Params);
    bool ValidatePathName(const CString& PathName, unsigned int & PathType) const;
    void OnCustDraw(NMHDR *pNotifyStruct, LRESULT *pResult);
    // Generated message map functions
	//{{AFX_MSG(CListCtrlEx)
    BOOL PreTranslateMessage(MSG* pMsg);

	afx_msg void OnDropFiles(HDROP DropInfo, CPoint Point);
	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

	afx_msg void OnMouseMove(UINT nFlags, CPoint Point);
	afx_msg void OnLButtonUp(UINT nFlags, CPoint Point);
	afx_msg void OnBeginDrag(NMHDR* pNMHDR, LRESULT* pResult);
	afx_msg void OnTimer(UINT IDEvent);
	afx_msg void OnDestroy();
	//}}AFX_MSG

	DECLARE_MESSAGE_MAP()

private:
    // Helper functions
    bool CheckFileExt(const tstring & ExtList, const tstring & Ext)const;

    COleDropTargetEx m_FilesDropDrop;
	CDWordArray	 m_DragSelIdxes;         // Selected items' index when dragging
	int m_DropIndex;
	CImageList*	 m_DragImage;
	int	m_PrevDropIndex;            
	UINT m_PrevDropState;
	DWORD m_ListStyle;
	UINT  m_ScrollTimer;
	EScrollDirection m_ScrollDirection;
    LISTMODE m_CtrlMode;
	CToolTipCtrl m_ToolTip;              // Tool tip control
    BOOL m_EnableTips;                   // Indicates wether we have enabled to show tips 
    int m_TipsPreItemIdx;                // Previous item the mouse on
    int m_FileDragPreItemIdx;            // Previous item the mouse on when in file drag & drop

    COLORREF m_PlayingTextColor;         // Playing song 's color of the text
    COLORREF m_PlayingTextBgColor;       // Playing song 's color of the text background
    int m_CurSongIdx;                    // Current playing song
};